#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#ifdef WIN32
#include "windows.h"
#endif

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"
#include "pthread.h"

#include "BList.h"
#include "BVector.h"
#include "geometrics.h"
#include "quaternion.h"
#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"
#include "FTKBase.h"

#include "AWEntity.h"
#include "AWMessage.h"
#include "AWBrain.h"
#include "AWTracerBrain.h"
#include "AWThreadedBrain.h"
#include "AWNOOSBrain.h"
#include "AWNOOSLearnerBrain.h"

#include "CaseBaseUtils.h"

#include "psm.h"

#include "loader.h"



AW_NOOSLearnerBrain::AW_NOOSLearnerBrain(Ontology *O,FTKBase *Memory,FTKBase *CB,bool pause) : AW_NOOSBrain(O,Memory,CB,pause) 
{
	class_name->set("AW_NOOSLearnerBrain");

	m_learning_method=new Symbol("LID");
	m_collaboration_strategy=new Symbol("individual");
	m_retention_strategy=new Symbol("NR");
	m_amal2_retention_strategy=new Symbol("NR");
	m_generate_counterarguments=true;
	m_generate_counterexamples=true;

	last_problem_solved=0;

	BCCS_CM_accuracy[0]=0;
	BCCS_CM_accuracy[1]=0;
	BCCS_CM_accuracy[2]=0;
	BCCS_CM_accuracy[3]=0;

} /* AW_NOOSLearnerBrain::AW_NOOSLearnerBrain */ 



AW_NOOSLearnerBrain::AW_NOOSLearnerBrain(FILE *fp,Ontology *O,FTKBase *Memory,FTKBase *CB,bool pause) : AW_NOOSBrain(O,Memory,CB,pause) 
{
	class_name->set("AW_NOOSLearnerBrain");

	m_learning_method=new Symbol("LID");
	m_collaboration_strategy=new Symbol("individual");
	m_retention_strategy=new Symbol("NR");
	m_amal2_retention_strategy=new Symbol("NR");
	m_generate_counterarguments=true;
	m_generate_counterexamples=true;

	last_problem_solved=0;

	BCCS_CM_accuracy[0]=0;
	BCCS_CM_accuracy[1]=0;
	BCCS_CM_accuracy[2]=0;
	BCCS_CM_accuracy[3]=0;

	load(fp);
} /* AW_NOOSLearnerBrain::AW_NOOSLearnerBrain */ 


AW_NOOSLearnerBrain::~AW_NOOSLearnerBrain()
{
	if (m_collaboration_strategy!=0) delete m_collaboration_strategy;
	m_collaboration_strategy=0;

	if (m_learning_method!=0) delete m_learning_method;
	m_learning_method=0;

	if (m_retention_strategy!=0) delete m_retention_strategy;
	m_retention_strategy=0;

	if (m_amal2_retention_strategy!=0) delete m_amal2_retention_strategy;
	m_amal2_retention_strategy=0;

	if (last_problem_solved!=0) delete last_problem_solved;
	last_problem_solved=0;

} /* AW_NOOSLearnerBrain::~AW_NOOSLearnerBrain */ 


bool AW_NOOSLearnerBrain::load(FILE *fp) 
{
	if (!AW_NOOSBrain::load(fp)) return false;

	if (m_learning_method!=0) delete m_learning_method;
	m_learning_method=new Symbol(fp);

	if (m_collaboration_strategy!=0) delete m_collaboration_strategy;
	m_collaboration_strategy=new Symbol(fp);

	if (m_retention_strategy!=0) delete m_retention_strategy;
	m_retention_strategy=new Symbol(fp);

	if (m_amal2_retention_strategy!=0) delete m_amal2_retention_strategy;
	m_amal2_retention_strategy=new Symbol(fp);

	if (m_collaboration_strategy->cmp("IBA2A-ONLYCE"))  {
		m_collaboration_strategy->set("IBA2A");
		m_generate_counterarguments=false;
	} /* if */ 
	if (m_collaboration_strategy->cmp("IBA2A-ONLYCA"))  {
		m_collaboration_strategy->set("IBA2A");
		m_generate_counterexamples=false;
	} /* if */ 

	return true;
} /* AW_NOOSLearnerBrain::load */ 


bool AW_NOOSLearnerBrain::save(FILE *fp) 
{
	if (!AW_NOOSBrain::save(fp)) return false;

	m_learning_method->save(fp);
	m_collaboration_strategy->save(fp);
	m_retention_strategy->save(fp);
	m_amal2_retention_strategy->save(fp);

	return true;
} /* AW_NOOSLearnerBrain::save */ 


bool AW_NOOSLearnerBrain::is_a(char *c)
{
	if (strcmp(c,"AW_NOOSLearnerBrain")==0) return true;

	return AW_NOOSBrain::is_a(c);
} /* AW_NOOSLearnerBrain::is_a */ 


bool AW_NOOSLearnerBrain::is_a(Symbol *c)
{
	if (c->cmp("AW_NOOSLearnerBrain")) return true;

	return AW_NOOSBrain::is_a(c);
} /* AW_NOOSLearnerBrain::is_a */ 


List<Symbol> *AW_NOOSLearnerBrain::get_friends(void)
{
	FeatureTerm *f;
	List<Symbol> *l=new List<Symbol>;

	pthread_mutex_lock(&m_sensor_data_mutex);
	m_sensor_data.Rewind();
	while(m_sensor_data.Iterate(f)) {						
		if (f->getSort()->is_a(m_ontology->get_sort("sensed-agent")) &&
			!f->getSort()->is_a(m_ontology->get_sort("sensed-self"))) {
			Symbol *name=f->featureValueQuick("name")->getSymbol();
			if (name->get()[0]=='L' &&
				name->get()[1]=='e' &&
				name->get()[2]=='a' &&
				name->get()[3]=='r' &&
				name->get()[4]=='n' &&
				name->get()[5]=='e' &&
				name->get()[6]=='r') {
				l->Add(new Symbol(name));
			} /* if */ 		
		} /* if */ 
	} /* while */ 
	pthread_mutex_unlock(&m_sensor_data_mutex);	
	return l;
} /* AW_NOOSLearnerBrain::get_friends */ 


void AW_NOOSLearnerBrain::thread(void)
{
	AW_Message *m;
	FeatureTerm *content;

	test_status();

	while(true) {
		{
			/* Set the color of the agent to "ready": */ 
			FeatureTerm *op=FeatureTerm::fromStringNOOS("(define (color-operator) (r 0.6) (g 0.6) (b 0.6))",m_memory,m_ontology);
			enqueue_operator(op);
		}
		wait_message();
		m=get_message();
		content=FeatureTerm::fromStringNOOS(m->content->get(),m_memory,m_ontology);
		process_message(m,content);
		delete content;
		test_status();

		delete m;
	} /* while */ 

} /* AW_NOOSLearnerBrain::thread */ 


bool AW_NOOSLearnerBrain::process_message(AW_Message *m,FeatureTerm *content)
{	
	Symbol *my_name;
	my_name=m->receiver;

//	write_debug_report("[%s]: message received from %s\n",my_name->get(),m->sender->get());
//	write_debug_report("%s\n",m->content->get());

/*
	{
		char *s;
		s=content->toStringNOOS(m_memory);
		write_debug_report("[%s]: message content: %s\n",m->receiver->get(),s);
		delete []s;
	}
*/
	// learn-message ----------------------------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("learn-message")) {
		/* Learn a new case or set of cases: */ 
		FeatureTerm *tmp,*c,*op;

		tmp=content->featureValue("case");

		write_debug_report("[%s]: learnt cases: ",my_name->get());

		if (tmp->isSet()) {
			List<FeatureTerm> *l;
			l=tmp->set_values();
			while(!l->EmptyP()) {
				c=l->ExtractIni();
				write_debug_report("%s ",c->getName()->get());
				m_casebase->AddFT(c);
			} /* while */ 
			delete l;
		} else {
			write_debug_report("[%s]: learnt cases: %s\n",my_name->get(),tmp->getName()->get());
			m_casebase->AddFT(new FeatureTerm(tmp));
		} /* if */ 

		write_debug_report("\n");

		/* Send back a confirmation: */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
						   "content",new FeatureTerm(0,new Symbol("(define (any))"),m_ontology));
		enqueue_operator(op);

		delete tmp;
		return true;
	} /* if */ 


	// learn-message-iba ------------------------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("learn-message-iba")) {
		/* Learn a new case or set of cases: */ 
		FeatureTerm *tmp,*c,*op;

		tmp=content->featureValue("case");

		if (tmp->isSet()) {
			List<FeatureTerm> *l;
			l=tmp->set_values();
			while(!l->EmptyP()) {
				c=l->ExtractIni();
				write_debug_report("[%s]: learnt case IBA %s\n",m->receiver->get(),c->getName()->get());
				received_cases_IBA2A.Add(c);
			} /* while */ 
			delete l;
		} else {
			write_debug_report("[%s]: learnt case %s\n",m->receiver->get(),tmp->getName()->get());
			received_cases_IBA2A.Add(new FeatureTerm(tmp));
		} /* if */ 

		/* Send back a confirmation: */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
						   "content",new FeatureTerm(0,new Symbol("(define (any))"),m_ontology));
		enqueue_operator(op);

		delete tmp;
		return true;
	} /* if */ 


	// reset-iba --------------------------------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("reset-iba")) {
		FeatureTerm *op;

		/* Appply retention strategy: */ 
		retain_cases(&received_cases_IBA2A,m_amal2_retention_strategy);

		received_cases_IBA2A.Delete();
		already_sent_cases_IBA2A.Delete();
		write_debug_report("[%s]: IBA protocol reset.\n",m->receiver->get());			
		/* Send back a confirmation: */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
						   "content",new FeatureTerm(0,new Symbol("(define (any))"),m_ontology));
		enqueue_operator(op);
	} /* if */ 


	// reset-test-iba --------------------------------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("reset-test-iba")) {
		FeatureTerm *op;

		/* Since it is a TEST problem, do not retain any case, and directly delete the lists: */ 
		received_cases_IBA2A.Delete();
		already_sent_cases_IBA2A.Delete();
		write_debug_report("[%s]: IBA protocol reset.\n",m->receiver->get());			
		/* Send back a confirmation: */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
						   "content",new FeatureTerm(0,new Symbol("(define (any))"),m_ontology));
		enqueue_operator(op);
		return true;
	} /* if */ 


	// forget-message ---------------------------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("forget-message")) {
		FeatureTerm *op;

		CB_size.Add(new int(m_casebase->get_n_terms()));
		m_casebase->Delete();
		already_sent_cases_IBA2A.Delete();
		JBartering_refutationsets_agent_name.Delete();
		JBartering_refutationsets.Delete();
		write_debug_report("[%s]: case base deleted.\n",my_name->get());			

		/* Show statistics: */ 
		// B-CCS
		if (!BCCS_committe_size.EmptyP()) {
			int average=0;
			int i;
			int max=0,*size;
			int *times_per_size;

			BCCS_committe_size.Rewind();
			while(BCCS_committe_size.Iterate(size)) {
				if (*size>max) max=*size;
				average+=*size;
			} /* while */ 

			write_debug_report("[B-CCS : %s]: Average committee size: %g\n",my_name->get(),float(average)/BCCS_committe_size.Length());	

			times_per_size=new int[max];
			for(i=0;i<max;i++) times_per_size[i]=0;
			BCCS_committe_size.Rewind();
			while(BCCS_committe_size.Iterate(size)) {
				times_per_size[(*size)-1]++;
			} /* while */ 
			for(i=0;i<max;i++) {
				write_debug_report("[B-CCS : %s]: Committees of size.%i: %i [%g%%]\n",my_name->get(),i+1,times_per_size[i],float(times_per_size[i])/BCCS_committe_size.Length());	
			} /* for */ 

			delete []times_per_size;

			// Competende model accuracy:
			{
				int total=BCCS_CM_accuracy[0]+BCCS_CM_accuracy[1]+BCCS_CM_accuracy[2]+BCCS_CM_accuracy[3];

				write_debug_report("Competence model Accuracy: \n");
				write_debug_report("                           Correct  Incorrect \n");
				write_debug_report("CM predicted Correct   ->    %.3f     %.3f\n", float(BCCS_CM_accuracy[0])/total,float(BCCS_CM_accuracy[2])/total);
				write_debug_report("CM predicted Incorrect ->    %.3f     %.3f\n", float(BCCS_CM_accuracy[1])/total,float(BCCS_CM_accuracy[3])/total);
				write_debug_report("Accuracy: %g\n", float(BCCS_CM_accuracy[0]+BCCS_CM_accuracy[3])/total);
				write_debug_report("Failed cases because of CM: %i\n", BCCS_CM_accuracy[2]);
			}
			
		} /* if */ 
		// CB size:
		{
			int average=0;
			int *size;

			CB_size.Rewind();
			while(CB_size.Iterate(size)) {
				average+=*size;
			} /* while */ 

			write_debug_report("[%s]: Average CB size: %g\n",my_name->get(),float(average)/CB_size.Length());
		}

		/* Send back a confirmation: */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
						   "content",new FeatureTerm(0,new Symbol("(define (any))"),m_ontology));
		enqueue_operator(op);
		return true;
	} /* if */ 


	// request-casebase-size ---------------------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("request-casebase-size")) {
		FeatureTerm *op;
		char s[256];

		sprintf(s,"%i",m_casebase->get_n_terms());

		/* Send back the size of the case base: */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
						   "content",new FeatureTerm(0,new Symbol(s),m_ontology));
		enqueue_operator(op);
		return true;
	} /* if */ 


	// request-individual-predict-message -------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("request-individual-predict-message")) {
		FeatureTerm *op;
		FeatureTerm *problem;
		FeatureTerm *answer;
		char *s;

		{
			/* Set the color of the agent to "working": */ 
			FeatureTerm *op;
			op=FeatureTerm::fromStringNOOS("(define (color-operator) (r 1.0) (g 0.4) (b 0.4))",m_memory,m_ontology);
			enqueue_operator(op);
		}

		problem=content->featureValue("problem");
		if (last_problem_solved!=0) delete last_problem_solved;
		last_problem_solved=new FeatureTerm(problem);

		/* Solve the problem individually: */ 
		{
			Sort *sort=get_case_sort(m_ontology,problem->getSort());

			answer = build_jers(problem,sort,my_name);
			s=answer->toStringNOOS(m_memory);
			delete answer;
		}

		/* Send back the solution: */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
						   "content",new FeatureTerm(0,new Symbol(s),m_ontology));
		enqueue_operator(op);
		delete []s;

		delete problem;
		return true;
	} /* if */ 



	// request-individual-single-predict-message ------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("request-individual-single-predict-message")) {
		FeatureTerm *op;
		FeatureTerm *problem;
		FeatureTerm *answer;
		char *s;

		{
			/* Set the color of the agent to "working": */ 
			FeatureTerm *op;
			op=FeatureTerm::fromStringNOOS("(define (color-operator) (r 1.0) (g 0.4) (b 0.4))",m_memory,m_ontology);
			enqueue_operator(op);
		}

		problem=content->featureValue("problem");
		if (last_problem_solved!=0) delete last_problem_solved;
		last_problem_solved=new FeatureTerm(problem);

		/* Solve the problem individually: */ 
		{
			Sort *sort=get_case_sort(m_ontology,problem->getSort());

			answer = build_single_jer(problem,sort,my_name);
			s=answer->toStringNOOS(m_memory);
			delete answer;
		}

		/* Send back the solution: */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
						   "content",new FeatureTerm(0,new Symbol(s),m_ontology));
		enqueue_operator(op);
		delete []s;

		delete problem;
		return true;
	} /* if */ 


	// request-prediction-message ---------------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("request-prediction-message") ||
		content->getSort()==m_ontology->get_sort("request-test-prediction-message")) {
		bool test=false;
		FeatureTerm *op;
		FeatureTerm *problem;
		FeatureTerm *answer;
		char *s;
		Symbol *cs=m_collaboration_strategy;

		{
			FeatureTerm *f;
			f=content->featureValue("strategy");
			if (f!=0 && f->isSymbol()) cs=f->getSymbol();
			delete f;
		}

		if (content->getSort()==m_ontology->get_sort("request-test-prediction-message")) test=true;

		{
			/* Set the color of the agent to "working": */ 
			FeatureTerm *op;
			op=FeatureTerm::fromStringNOOS("(define (color-operator) (r 1.0) (g 0.4) (b 0.4))",m_memory,m_ontology);
			enqueue_operator(op);
		}

		problem=content->featureValue("problem");
		if (last_problem_solved!=0) delete last_problem_solved;
		last_problem_solved=new FeatureTerm(problem);

		{
			Sort *sort=get_case_sort(m_ontology,problem->getSort());

			/* Solve the problem: */ 
			answer=0;
			if (cs->cmp("individual")) answer = solve_problem_individually(problem,sort,my_name);
			if (cs->cmp("committee")) answer = solve_problem_committee(problem,sort,my_name);
			if (cs->cmp("simple-committee")) answer = solve_problem_simple_committee(problem,sort,my_name);
			if (cs->cmp("B-CCS")) answer = solve_problem_bounded(problem,sort,my_name);
			if (cs->cmp("JEC")) answer = solve_problem_JEC(problem,sort,my_name);
			if (cs->cmp("IBA2A")) answer = solve_problem_IBA2A(problem,sort,my_name,test);
			if (cs->cmp("IBA")) answer = solve_problem_IBA_convener(problem,sort,my_name,test);
			if (cs->cmp("JBartering")) answer = solve_problem_JBartering(problem,sort,my_name,test);

//				if (answer==0) answer = solve_problem_individually(problem,sort,my_name);
			if (answer==0) {
				s=new char[15];
				strcpy(s,"(define (any))");
			} else {
				s=answer->toStringNOOS(m_memory);
				delete answer;
			} /* if */ 
		}

		cs=0;

		/* Send back the solution: */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
						   "content",new FeatureTerm(0,new Symbol(s),m_ontology));
		enqueue_operator(op);
		delete []s;

		delete problem;
		return true;
	} /* if */ 


	// solution-inform-message ---------------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("solution-inform-message") ||
		content->getSort()==m_ontology->get_sort("solution-test-inform-message")) {
		bool test=false;
		List<FeatureTerm> case_l;
		FeatureTerm *op;
		FeatureTerm *solution=content->featureValue("solution");

		if (content->getSort()==m_ontology->get_sort("solution-test-inform-message")) test=true;

		if (last_problem_solved!=0) {
			FeatureTerm *c;
			c=build_case(last_problem_solved,solution,m_ontology);
			case_l.Add(c);

			char *tmp;
			tmp=solution->toStringNOOS(m_memory);
			write_debug_report("[%s]: Correct solution to the last problem(%s): %s\n",my_name->get(),last_problem_solved->getName()->get(),tmp);
			delete []tmp;
		} else {
			write_debug_report("[%s]: ERROR: Correct solution received, but no last problem!!!\n",my_name->get());
		} /* if */ 

		/* Evaluate competence model accuracy: */ 
		{
			FeatureTerm *s;
			bool *p;
			bool correct;

			while(!BCCS_CM_Candidate_Solution.EmptyP()) {
				s=BCCS_CM_Candidate_Solution.ExtractIni();
				p=BCCS_CM_Prediction.ExtractIni();

				correct=false;
				if (s->equivalents(solution)) correct=true;

				if (correct) {
					if (*p) BCCS_CM_accuracy[0]++;
					   else BCCS_CM_accuracy[1]++;
				} else {
					if (*p) BCCS_CM_accuracy[2]++;
					   else BCCS_CM_accuracy[3]++;
				} /* if */ 

				delete s;
				delete p;
			} /* while */ 
		}

		// Perform all the J-Bartering related actions: */ 
//			JBartering(solution,get_case_sort(m_ontology,last_problem_solved->getSort()),my_name,test);
//			JBartering_unfair(solution,get_case_sort(m_ontology,last_problem_solved->getSort()),my_name,test);
		JBartering_nonstrict(solution,get_case_sort(m_ontology,last_problem_solved->getSort()),my_name,test);

		/* Engage Retention strategy (only if the problem is not a TEST one): */ 
		if (!test) retain_cases(&case_l,m_retention_strategy);

		/* Send back a confirmation: */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
						   "content",new FeatureTerm(0,new Symbol("(define (any))"),m_ontology));
		enqueue_operator(op);

		delete solution;
		return true;
	} /* if */ 

	// request-examination-message --------------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("request-examination-message")) {
		FeatureTerm *op;
		FeatureTerm *problem;
		FeatureTerm *JERs,*JER;
		FeatureTerm *XERs;
		char *s;

		{
			/* Set the color of the agent to "working": */ 
			FeatureTerm *op;
			op=FeatureTerm::fromStringNOOS("(define (color-operator) (r 1.0) (g 0.4) (b 0.4))",m_memory,m_ontology);
			enqueue_operator(op);
		}

		JERs=content->featureValue("prediction");
		problem=content->featureValue("problem");

		if (JERs==0 || problem==0) write_debug_report("em: ERROR 1\n");

		/* Examine the JER: */ 
		{
			Sort *sort=get_case_sort(m_ontology,problem->getSort());

			if (sort==0) write_debug_report("em: ERROR 2\n");

			XERs=FeatureTerm::SetFeatureTerm((Symbol *)0);

			if (JERs->isFeatureTerm()) {
				XERs->addSetValue(examine_JER(JERs,sort));
			} else {
				List<FeatureTerm> *l;
				l=JERs->set_values_quick();
				l->Rewind();
				while(l->Iterate(JER)) {
					XERs->addSetValue(examine_JER(JER,sort));
				} /* while */ 
			} /* if */ 

			s=XERs->toStringNOOS(m_memory);
			delete XERs;
		}

		/* Send back the solution: */ 
		op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
						   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
						   "content",new FeatureTerm(0,new Symbol(s),m_ontology));
		enqueue_operator(op);
		delete []s;

		delete JERs;
		delete problem;
		return true;
	} /* if */ 


	// request-counterargument --------------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("request-counterargument")) {
		FeatureTerm *JER,*problem,*op,*historic;
		FeatureTerm *counterargument;
		List<FeatureTerm> historic_list;
		Sort *sort=0;

		{
			/* Set the color of the agent to "working": */ 
			FeatureTerm *op;
			op=FeatureTerm::fromStringNOOS("(define (color-operator) (r 1.0) (g 0.4) (b 0.4))",m_memory,m_ontology);
			enqueue_operator(op);
		}
	
		JER=content->featureValue("jer");
		problem=content->featureValue("problem");
		historic=content->featureValue("historic");
		if (historic!=0) {
			if (historic->isFeatureTerm()) {
				historic_list.Add(new FeatureTerm(historic));
			} else {
				List<FeatureTerm> *l;
				FeatureTerm *f;

				l=historic->set_values_quick();
				l->Rewind();
				while(l->Iterate(f)) {
					historic_list.Add(new FeatureTerm(f));
				} /* while */ 
			} /* if */ 
			delete historic;
		} /* if */ 

		sort=get_case_sort(m_ontology,problem->getSort());

		counterargument=generate_attacking_JER(problem,JER,&historic_list,sort,my_name);

		if (counterargument==0) {
			counterargument=generate_counterexample(&already_sent_cases_IBA2A,JER,sort);
		} /* if */ 

		if (counterargument==0) {
			op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
							   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
							   "content",new FeatureTerm(0,new Symbol("(define (any))"),m_ontology));
		} else {
			char *s;
			s=counterargument->toStringNOOS(m_memory);
			op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
							   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
							   "content",new FeatureTerm(0,new Symbol(s),m_ontology));
			delete []s;
		} /* if */ 
		enqueue_operator(op);

		delete problem;
		delete JER;
		return true;
	} /* if */ 



	// request-iba-collaboration-message ----------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("request-iba-collaboration-message") ||
		content->getSort()==m_ontology->get_sort("request-test-iba-collaboration-message")) {
		bool test=false;
		FeatureTerm *problem;

		if (content->getSort()==m_ontology->get_sort("request-test-iba-collaboration-message")) test=true;

		{
			/* Set the color of the agent to "working": */ 
			FeatureTerm *op;
			op=FeatureTerm::fromStringNOOS("(define (color-operator) (r 1.0) (g 0.4) (b 0.4))",m_memory,m_ontology);
			enqueue_operator(op);
		}

		problem=content->featureValue("problem");
		if (last_problem_solved!=0) delete last_problem_solved;
		last_problem_solved=new FeatureTerm(problem);

		{
			Sort *sort=get_case_sort(m_ontology,problem->getSort());

			solve_problem_IBA_other(problem,sort,my_name,m->sender,test);
		}

		delete problem;		
		return true;
	} /* if */ 


	// jbartering-cases ---------------------------------------------------------------------------
	if (content->getSort()==m_ontology->get_sort("jbartering-cases")) {
		List<FeatureTerm> *cases1,*cases2;
//			int n1,n2,n3;
		int n1,n2,n1f,n2f;
		FeatureTerm *c;

		cases1=content->featureValueQuick("cases")->set_values_quick();
		n1f=n1=cases1->Length();
		{
			int pos=JBartering_refutationsets_agent_name.Position(m->sender);
			if (pos==-1) {
				cases2=new List<FeatureTerm>;
			} else {
//					cases2=JBartering_cases_to_offer(JBartering_refutationsets[pos],n1);
				cases2=JBartering_cases_to_offer(JBartering_refutationsets[pos],-1);
			} /* if */ 
		}
		n2f=n2=cases2->Length();
		
		// unfair
		// ...
		// non strict
		if (n1==0 || n2==0) n1f=n2f=0;
		// strict:
//			n1f=min(n1,n2);
//			n2f=min(n1,n2);

		write_debug_report("[%s] Received Offer from %s: ",my_name->get(),m->sender->get());
		cases1->Rewind();
		while(cases1->Iterate(c)) {
			write_debug_report("%s ",c->getName()->get());
		} /* while */ 
		write_debug_report("\n");
		write_debug_report("[%s] %i,%i cases exchanged(2).\n",my_name->get(),n1f,n2f);

		// Retain the first 'n3' cases of 'cases1':
		{
			int i;
			for(i=0;i<n1f;i++) retain_case(new FeatureTerm(cases1->operator [](i)));
		}

		// Send the first 'n3' cases of 'cases2':
		{
			FeatureTerm *f=FeatureTerm::SetFeatureTerm((Symbol *)0);
			FeatureTerm *msg,*op;
			char *str;
			int i;
			for(i=0;i<n2f;i++) f->addSetValue(new FeatureTerm(cases2->operator [](i)));

			msg=new FeatureTerm((char *)0,m_ontology->get_sort("jbartering-cases"),1,
								"cases",f);

			str=msg->toStringNOOS(m_memory);
			op=new FeatureTerm((char *)0,m_ontology->get_sort("send-operator"),2,
							   "receiver",new FeatureTerm(0,new Symbol(m->sender),m_ontology),
							   "content",new FeatureTerm(0,new Symbol(str),m_ontology));
			delete []str;
			delete msg;
			enqueue_operator(op);
		}

		// Remove the first 'n3' cases from the list of cases to send:
		{
			int i;
			List< List<FeatureTerm> > to_delete,*l;
			List<FeatureTerm> *l2,*l_tmp;

			i=JBartering_refutationsets_agent_name.Position(m->sender);
			l=JBartering_refutationsets[i];

			for(i=0;i<n2f;i++) {
				c=cases2->operator [](i);
				l->Rewind();
				while(l->Iterate(l2)) {
					int pos;
					pos=l2->Position(c);
					if (pos!=-1) l2->DeletePosition(pos);

					if (l2->EmptyP() && !to_delete.MemberRefP(l2)) to_delete.Add(l2);
				} /* while */ 
			} /* for */ 

			while(!to_delete.EmptyP()) {
				l_tmp=to_delete.ExtractIni();
				l->DeleteElement(l_tmp);
				delete l_tmp;
			} /* while */ 
		}
		delete cases2;
		return true;
	} /*if */ 

	return false;
} /* AW_NOOSLearnerBrain::process_message */ 
 

FeatureTerm *AW_NOOSLearnerBrain::build_jers(FeatureTerm *problem,Sort *sort,Symbol *agent_name)
{
	FeatureTerm *solution_record=0,*c;
	Prediction *p=0;
	List<FeatureTerm> *cases=0;
	Path dp,sp;

	if (agent_name==0) {
		write_debug_report("[build_jers]: no agent name provided!!!!!\n");
	} /* if */ 

	/* Retrieve precedents: */ 
	cases=m_casebase->SearchFT(sort);

	received_cases_IBA2A.Rewind();
	while(received_cases_IBA2A.Iterate(c)) cases->Add(c);

	write_debug_report("[AW_NOOSLearnerBrain]: solving with %i cases\n",cases->Length());

	/* Build description and solution paths: */ 
	dp.Add(new Symbol("description"));
	sp.Add(new Symbol("solution"));
	if (strcmp(problem->getSort()->get(),"sponge")==0) {
		sp.Add(new Symbol("order"));
	} /* if */ 
	
	/* call problem solving method: */ 
//	if (m_learning_method->cmp("rLID1")) p=refinement_LID(problem,cases,&dp,&sp,m_ontology,m_memory,1,0,1);
//	if (m_learning_method->cmp("rLID2")) p=refinement_LID2(problem,cases,&dp,&sp,m_ontology,m_memory,1,0,1);
	if (m_learning_method->cmp("rLID3")) p=refinement_LID3(problem,cases,&dp,&sp,m_ontology,m_memory,1,0,1);
	if (p==0) p=eva_LID(problem,cases,&dp,&sp,m_ontology,m_memory,1,0,1);

	cases->ExtractAll();
	delete cases;

	/* build solution record: */ 
	write_debug_report("[AW_NOOSLearnerBrain]: proposed %i JERs\n",p->solutions.Length());
	if (p->solutions.Length()==1) {
		solution_record=new FeatureTerm((char *)0,m_ontology->get_sort("problem-prediction"),4,
//										"problem",new FeatureTerm(p->problem),
										"solution",new FeatureTerm(p->solutions[0]),
										"support",new FeatureTerm((char *)0,*p->support[0],m_ontology),
										"justification",new FeatureTerm(p->justifications[0]),
										"agent",new FeatureTerm(0,new Symbol(agent_name),m_ontology));
	} else {
		int i;
		solution_record=FeatureTerm::SetFeatureTerm((Symbol *)0);

		for(i=0;i<p->solutions.Length();i++) {
			solution_record->addSetValue(new FeatureTerm((char *)0,m_ontology->get_sort("problem-prediction"),4,
//														 "problem",new FeatureTerm(p->problem),
														 "solution",new FeatureTerm(p->solutions[i]),
														 "support",new FeatureTerm((char *)0,*p->support[i],m_ontology),
														 "justification",new FeatureTerm(p->justifications[i]),
														 "agent",new FeatureTerm(0,new Symbol(agent_name),m_ontology)));
		} /* for */ 
	} /* if */ 

	delete p;
/*
	{
		char *str;
		str=solution_record->toStringNOOS(m_memory);
		write_debug_report("[AW_NOOSLearnerBrain]: solution:\n%s\n\n",str);
		delete []str;
	}
*/

	return solution_record;
} /* AW_NOOSLearnerBrain::build_jers */ 



FeatureTerm *AW_NOOSLearnerBrain::build_single_jer(FeatureTerm *problem,Sort *sort,Symbol *agent_name)
{
	FeatureTerm *solution_record=0,*c;
	Prediction *p=0;
	List<FeatureTerm> *cases=0;
	Path dp,sp;

	if (agent_name==0) {
		write_debug_report("[build_single_jer]: no agent name provided!!!!!\n");
	} /* if */ 

	/* Retrieve precedents: */ 
	cases=m_casebase->SearchFT(sort);

	received_cases_IBA2A.Rewind();
	while(received_cases_IBA2A.Iterate(c)) cases->Add(c);

	write_debug_report("[AW_NOOSLearnerBrain]: solving with %i cases\n",cases->Length());

	/* Build description and solution paths: */ 
	dp.Add(new Symbol("description"));
	sp.Add(new Symbol("solution"));
	if (strcmp(problem->getSort()->get(),"sponge")==0) {
		sp.Add(new Symbol("order"));
	} /* if */ 
	
	/* call problem solving method: */ 
//	if (m_learning_method->cmp("rLID1")) p=refinement_LID(problem,cases,&dp,&sp,m_ontology,m_memory,1,0,1);
//	if (m_learning_method->cmp("rLID2")) p=refinement_LID2(problem,cases,&dp,&sp,m_ontology,m_memory,1,0,1);
	if (m_learning_method->cmp("rLID3")) p=refinement_LID3(problem,cases,&dp,&sp,m_ontology,m_memory,1,0,1);
	if (p==0) p=eva_LID(problem,cases,&dp,&sp,m_ontology,m_memory,1,0,1);

	while(!cases->EmptyP()) cases->ExtractIni();
	delete cases;

	/* build solution record: */ 
	write_debug_report("[AW_NOOSLearnerBrain]: proposed %i JERs\n",p->solutions.Length());
	if (p->solutions.Length()==1) {
		write_debug_report("[AW_NOOSLearnerBrain]: support: %i\n",*p->support[0]);
		solution_record=new FeatureTerm((char *)0,m_ontology->get_sort("problem-prediction"),4,
//										"problem",new FeatureTerm(p->problem),
										"solution",new FeatureTerm(p->solutions[0]),
										"support",new FeatureTerm((char *)0,*p->support[0],m_ontology),
										"justification",new FeatureTerm(p->justifications[0]),
										"agent",new FeatureTerm(0,new Symbol(agent_name),m_ontology));
	} else {
		int i;
		int selected=0;

		for(i=0;i<p->solutions.Length();i++) {
			if (*p->support[i]>*p->support[selected]) selected=i;
			write_debug_report("[AW_NOOSLearnerBrain]: support: %i\n",*p->support[i]);
		} /* if */ 
		write_debug_report("[AW_NOOSLearnerBrain]: selected %i\n",selected);

		solution_record=new FeatureTerm((char *)0,m_ontology->get_sort("problem-prediction"),4,
//										"problem",new FeatureTerm(p->problem),
										"solution",new FeatureTerm(p->solutions[selected]),
										"support",new FeatureTerm((char *)0,*p->support[selected],m_ontology),
										"justification",new FeatureTerm(p->justifications[selected]),
										"agent",new FeatureTerm(0,new Symbol(agent_name),m_ontology));
	} /* if */ 

	delete p;
/*
	{
		char *str;
		str=solution_record->toStringNOOS(m_memory);
		write_debug_report("[AW_NOOSLearnerBrain]: solution:\n%s\n\n",str);
		delete []str;
	}
*/

	return solution_record;
} /* AW_NOOSLearnerBrain::build_single_jer */ 



FeatureTerm *AW_NOOSLearnerBrain::solve_problem_individually(FeatureTerm *problem,Sort *sort,Symbol *my_name)
{
	List<FeatureTerm> individual_solutions;

	/* Solve the problem individually: */ 
	individual_solutions.Add(build_jers(problem,sort,my_name));

	/* Aggregate the solutions: */ 
	return BWAV(&individual_solutions);
} /* AW_NOOSLearnerBrain::solve_problem_individually */ 

